﻿using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Net;
using System.Threading;

namespace FrameServer.Net
{

    class TCPServer : Singleton<TCPServer>
    {
        public Socket serverSocket;
        //所有已连接的TCPPeer。
        //可能是一些建立了tcp连接的但是未登录的客户端，还可能是一些已经断连但服务器未检测到断连的客户端
        public readonly List<TCPClientPeer> tcpClients = new List<TCPClientPeer>();
        //目前在线的TCPPeer
        public readonly Dictionary<string, TCPClientPeer> clientPeerMap = new Dictionary<string, TCPClientPeer>();


        public void StartServer()
        {
            IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse(ServerConfig.serverIP), ServerConfig.tcpPort);
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            serverSocket.Bind(iPEndPoint);
            serverSocket.Listen(10);
            serverSocket.BeginAccept(AcceptCallBack, null);
            LogUtil.Log("服务器启动成功...");

            //用来处理心跳包的线程
            new Thread(HandleHeartBeatPack).Start();
        }


        private void AcceptCallBack(IAsyncResult asyncResult)
        {
            try
            {
                Socket clientSocket = serverSocket.EndAccept(asyncResult);
                AddTCPClientPeer(clientSocket);
                LogUtil.Log($"{clientSocket.RemoteEndPoint} tcp客户端连接，当前连接数: {tcpClients.Count}");
            }
            catch (Exception e)
            {
                LogUtil.Log(e, LogLevel.WARN);
            }
            serverSocket.BeginAccept(AcceptCallBack, null);
        }

        private TCPClientPeer AddTCPClientPeer(Socket clientSocket) {
            TCPClientPeer client = new TCPClientPeer(clientSocket);
            tcpClients.Add(client);
            return client;
        }
        public void RemoveTCPClientPeer(TCPClientPeer client)
        {
            client.CloseTcpClient();
        }

        private void HandleHeartBeatPack()
        {
            while (true)
            {
                Thread.Sleep(ServerConfig.checkTime * 1000);
                for (int i = tcpClients.Count - 1; i >= 0; i--)
                {
                    TCPClientPeer client = tcpClients[i];
                    if (client.heartBeatFlag == false)
                    {
                        client.lackNum++;
                        LogUtil.Log($"{client.tcpIPEndPoint}未收到心跳包");
                        if (client.lackNum >= ServerConfig.beatNum)
                        {
                            LogUtil.Log($"{client.tcpIPEndPoint}超时未收到心跳包，释放其tcp连接");
                            RemoveTCPClientPeer(client);
                        }
                    }
                    else
                    {
                        client.lackNum = 0;
                        client.heartBeatFlag = false;
                    }
                }
            }
        }

        public TCPClientPeer GetTcpPeer(string token)
        {
            if (clientPeerMap.TryGetValue(token, out TCPClientPeer peer))
                return peer;
            else
                return null;
        }
    }
}
